home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Networking / ARPSample / Read Me About ARP Sample < prev   
Encoding:
Text File  |  2000-09-28  |  12.3 KB  |  166 lines  |  [TEXT/ttxt]

  1. ARPSample
  2.  
  3. 1.0b1
  4.  
  5. Address Resolution Protocol (ARP) is a protocol for mapping protocol (eg IP) addresses to hardware (eg Ethernet) addresses.  The OT ARP module provides an ARP service that is used by the OT TCP/IP stack. This sample demonstrates how you can get direct access to the ARP module to, amongst other things, add and remove ARP cache entries.
  6.  
  7. About ARP
  8.  
  9. Core Protocol
  10.  
  11. The basic operation of ARP is very simple. The ARP module keeps a cache of recent IP to hardware address translations.  When asked to transmit an IP packet, IP looks up the destination’s IP address in the ARP cache.  If it is in the cache, IP knows the hardware address where it should send the packet.  If the destination IP address isn’t in the ARP cache, ARP broadcasts an ARP Request packet saying “Who has this IP address?”  The machine with that IP address responds with an ARP Response packet saying “I have that IP address and here’s my hardware address.”  ARP puts this response into the ARP cache to avoid having to do this for each IP packet.
  12.  
  13. For more information about the ARP protocol, consult “Internetworking with TCP/IP Volume I” by Douglas Comer and David Stevens (Prentice Hall, ISBN 0-13-468505-9).  Make sure you get Volume I; the later volumes deal with more esoteric things.  You can also FTP the ARP protocol definition from:
  14.  
  15.   <ftp://ds.internic.net//std/std37.txt>
  16.  
  17. ARP Under Open Transport
  18.  
  19. Under Open Transport, ARP is provided as a STREAMS module combination.  The module supports messages to perform the basic ARP functionality, and some utility messages for general clients.
  20.  
  21. Because OT TCP/IP was designed to support multi-homing, ARP must be able to deal with ARP on multiple different network interfaces simultaneously.  Each interface over which ARP is running is given an interface name that is derived from the module name of the interface’s driver, followed by a number that uniquely identies the interface.  For example, the built-in Ethernet on a PCI PowerMac is controlled by a device driver called "mace", so the first ARP interface that uses this driver has an interface name of "mace0".
  22.  
  23. Note: TCP/IP under OT 1.1.x does not support multi-homing, so it will only activate one ARP interface active.  The ARP module itself, however, is capable of supporting multiple interfaces even under OT 1.1.x.
  24.  
  25. Because ARP operates indepently on each interface, it must maintain separate information for each interface.  So each entry in the ARP cache contains the following information:
  26.  
  27. • Interface
  28. • IP address
  29. • Hardware address
  30. • Flags
  31.  
  32. ARP works in two different ways depending on whether the ARP module ("arpm") is pushed or the ARP driver ("arp") is opened.  When acting as a module, ARP expects to be pushed on top of a DLPI device driver that controls an interface.  When acting as a driver itself, ARP will field ARP command requests from above.
  33.  
  34. Talking to ARP
  35.  
  36. The messages accepted by the OT ARP module allow you to:
  37.  
  38. • Add an ARP cache entry.
  39. • Add an ARP cache mapping.
  40. • Remove an ARP cache entry.
  41. • Look up an ARP cache entry.
  42. • Perform an ARP request, looking in the cache first, and then on the network.
  43. • Transmit an ARP request.
  44. • Transmit an ARP response.
  45. • Bring an ARP interface up.
  46. • Take an ARP interface up.
  47.  
  48. For detailed information about these messages, see "OTARPModule.h".
  49.  
  50. You can send these messages to the ARP module in one of two ways.  If you’re writing client code, it’s probably most convenient to send the message as an ioctl.  See the ARPDeleteEntry routine in "ARPerations.c" for a simple example of how to do this.
  51.  
  52. Alternatively, if you’re writing a STREAMS module, you can send these messages directly to the ARP module.  This sample does not have a good example of doing this, but it’s relatively straightforward.  Simply create an M_PROTO message whose contents are the ARP command (ie the memory buffer pointed to be ic_dp and ic_len in the ioctl case).  One gotcha with doing this that the response comes back as a M_CTL message.
  53.  
  54. User Level Operation
  55.  
  56. The sample includes a comprehensive, if somewhat primitive, shell program (ARPSampleShell) that I used to test and debug the code.  This shell program allows a number of user level operations that you can combine to do really interesting things.
  57.  
  58. To use the shell program, simply double click the appropriate application, ARPSampleShell.PPC on a PowerPC-based computer, ARPSampleShell.68K on a 68K-based computer. Once the program is running, you can enter single letter commands and then follow the on-screnn instructions.
  59.  
  60. Shell Program Reference
  61.  
  62. The ARPSampleShell program supports a number of simple commands that require little explanation:
  63.  
  64. 'p' — Print contents of ARP cache.
  65.  
  66. 'a' — Add an ARP cache entry. You are prompted for an interface name, the IP address, and the hardware (eg Ethernet) address it should be mapped to. You can also choose to set some ARP flags.
  67.  
  68. 'k' — Delete an ARP cache entry. You are prompted for an interface name and the IP address whose ARP cache entry you wish to delete.
  69.  
  70. 'l' — Lookup an ARP cache entry.  You are prompted for an interface name and the IP address whose ARP cache entry you wish to look up.  The resulting hardware address and flags are printed to the console.
  71.  
  72. In addition, the ARPSampleShell program lets you bring up ARPing interfaces completely independently of the OT TCP/IP stack.  Remember that OT TCP/IP normally brings up an ARP interface automatically when you start using TCP/IP.  These commands might be useful when you want to test the use of ARP independently from the TCP/IP stack.
  73.  
  74. The following interface commands are supported. 
  75.  
  76. 'i' — See the ARP interfaces we have brought up.  This will not show you the interface that is owned by TCP/IP, only the interfaces that this sample has brought up.
  77.  
  78. 'u' — Bring up a new ARP interface.  You are asked to enter a configuration for the interface, ie the string you would pass to OTCreateConfiguration.  Typically this would be the name of a port that you want to ARP on, eg "enet0".
  79.  
  80. 'd' — Tear down an ARP interface.  This command allows you to tear down an interface that you have brought up using ARPSampleShell.
  81.  
  82. Interesting Things To Do
  83.  
  84. You can combine the commands in some interesting ways.  For example, you can use 'u' to bring up an interface, then use 'a' to add a permanent, published cache entry for that interface.  This gets the machine to start ARPing for that IP address on that interface.
  85.  
  86. The Implementation
  87.  
  88. High-Level Overview
  89.  
  90. The sample is broken up into three parts:
  91.  
  92. • OTARPModule.h — This defines the interface to the ARP module, including the message types and formats.
  93. • ARPerations — This unit implements a high-level interface to the ARP module, including easy-to-call APIs for all the standard operations.
  94. • ARPSampleShell.c — This file provides the console window user interface to the sample.
  95.  
  96. Building the Sample
  97.  
  98. This sample builds with Metrowerks CodeWarrior 11 and the OT 1.1.1 interfaces. To build the sample, first open each project and set the “LatestInterfaces” and “LatestLibraries” access paths to point to your Open Transport interfaces and libraries. Then choose Make from the Project menu.
  99.  
  100. Once you have set the access paths, you can use the “Metrowerks Build Script” to rebuild the project automatically.
  101.  
  102. Packing List
  103.  
  104. Read Me About ARP Sample — This document.
  105.  
  106. ARPSample.PPC.µ — A PPC project to build the sample.
  107. ARPSample.PPC — A compiled version of the PPC project.
  108.  
  109. ARPSample.68K.µ — A 68K project to build the sample.
  110. ARPSample.68K — A compiled version of the 68K project.
  111.  
  112. ARPSampleShell.c — Source to the shell program that implements the user interface and allows you to 
  113.  
  114. ARPerations.h — The interface to my library of useful ARP functions.
  115. ARPerations.c — The implementation of my library of useful ARP functions.
  116.  
  117. OTARPModule.h — The interface to the Open Transport ARP module. This interface is made up of type definitions and constants for the ioctls used to talk to ARP.
  118.  
  119. Metrowerks Build Script — An AppleScript for rebuilding both projects.
  120.  
  121. Caveats
  122.  
  123. 1. When you are prompted to enter some information and instead you just hit return, ARPSampleShell uses a default value for that type of information. The default values for interface name, IP address and hardware address are all hardwired for my test environment.  Chances are that you will want to modify them for your environment.  You can do so by changing the constants kDefaultInterfaceName, kDefaultHardwareAddress, and kDefaultIPAddress. 
  124.  
  125. You can’t run the 68K version on the PPC.  This is because the raw streams API is not available to emulated clients on a PPC.  See DTS Q& NW48 for details:
  126.  
  127.   <http://devworld.apple.com/dev/qa/nw/nw48.html>
  128.  
  129. 2. Most of the development and testing of this sample was done on a PPC.  The 68K version seems to work, but I have more confindence in in the PPC version.
  130.  
  131. 3. One big question when using ARP is that of finding interface names.  ARP generates an interface name by appending a unique number, starting at 0, to the name of the driver for the interface.  For example, if the driver’s module name is “mace”, the first interface opened using that driver will be named “mace0”, the second “mace1”, and so on.
  132.  
  133. The problem here is that there’s no good way to interogate ARP for the list of interfaces that are currently active, so there’s no good way to predict which interface name ARP will allocate for a new interface that you bring up.
  134.  
  135. My solution is to guess that there will only be one interface per driver module, so that if you add an interface on top of “mace” it will be called “mace0”.  This is not an ideal solution.
  136.  
  137. There are two possible workarounds.  First, ARP has an SNMP interface that you can use to ask it for information about what interfaces it’s currently controlling.  Unfortunately I’m not in a possition to document that interface at the moment.  Second, you could probe the interface names by trying to, for example, add a mapping for a particular interface.  If you get an error, that interface is obviously not present, so you know what will happen if you add it.  However this workaround seems very kludgy, so I didn’t implement it.
  138.  
  139. One obvious workaround is to parse the results from ARPGetCacheReport, however this will not work in all cases because sometimes the interface names are too long to fit into the fixed field width used by the report.
  140.  
  141. 4. This sample does not show how to enumerate the contents of the ARP cache programmatically.  You can get the contents of the cache for user display (using ARPGetCacheReport), but not from software. Again, ARP has an SNMP interface to do this, but I’m not in a possition to document that interface at the moment.
  142.  
  143. 5. This sample does not demonstrate the use of AR_ENTRY_QUERY because I could not find a way of doing this effectively from client code.  Both of the mechanisms used to talk to ARP have fatal flaws that prevent you from making this command from the client side:
  144.  
  145. • The ioctl mechanism requires you to allocate a fixed sized buffer for the result.  Unfortunately, when ioctl sends the request to the ARP module, it sends the entire contents of this buffer.  When the ARP module responds, it sends you back the buffer you originally sent it followed by the request result.  When ioctl tries to copy this back into your buffer, it successfully manages to copy back the first chunk of data (ie the original ioctl buffer contents), but there is not enough space to copy back the ARP response.
  146.  
  147. • The M_PROTO mechanism doesn’t work because ARP responds to these requests using an M_CTL and the stream head drops these on the floor without notifying the client in any way.
  148.  
  149. The upshot of this is that you can’t issue this command without kernel side help.  The easiest workaround would be to implement a filter module that catches the M_CTL responses and converts them to M_PROTOs (or anything else) so that you can read them from your client side code.  I haven’t implemented this because it would require writing a STREAMS module, something way outside the scope of this sample.
  150.  
  151. 6. While the ARP protocol (and hence the ARP module) should be independent of protocol and hardware address formats, the ARP cache report only displays meaningful results for IP protocol addresses and Ethernet-style 6 byte hardware addresses.
  152.  
  153. Credits and Version History
  154.  
  155. Version 1.0d1 is the first released version, distributed to a small number of developers.
  156.  
  157. Version 1.0b1 is the first generally released version, which is virtually identical to 1.0d1.
  158.  
  159. Share and Enjoy.
  160.  
  161. Quinn “The Eskimo!”
  162. Developer Technical Support
  163. Networking, Communications, Hardware
  164.  
  165. 3 Apr 1997
  166.